/*
 * jpeg_mem.h
 *
 *  创建日期: 2016年1月19日
 *      作者: guyadong
 */

#ifndef FACEIMAGE_CIMGWRAPPER_JPEG_MEM_ADVANCE_H_
#define FACEIMAGE_CIMGWRAPPER_JPEG_MEM_ADVANCE_H_

 // 使用不同的宏定义来处理跨平台的导出/导入
#if defined(_WIN32) || defined(_WIN64)
#ifdef IMAGEWRAP_EXPORTS
#define IMAGEWRAP_API __declspec(dllexport)
#else
#define IMAGEWRAP_API __declspec(dllimport)
#endif
#else
#define IMAGEWRAP_API
#endif

#include <stdexcept>
#include <functional>
#include <string>
#include <vector>
#include <memory>
#include "jpeglib.h"
#include "jpeg_mem.h"

// 定义用于处理压缩/解压缩内存数据的回调函数类型
using mem_finish_output_fun = std::function<void(const uint8_t*, size_t)>;

// 定义自定义压缩/解压缩参数的函数对象类型
using jpeg_custom_output_fun = std::function<void(j_common_ptr)>;

// 默认的自定义输出函数声明
extern jpeg_custom_output_fun jpeg_custom_output_default;

/**
 * @brief 图像压缩接口类，定义压缩操作的基本接口
 */
IMAGEWRAP_API struct jpeg_compress_interface {
	// 用于存储图像扫描线行指针的缓冲区
	std::vector<JSAMPROW> buffer;

	// 自定义输出参数的函数对象
	jpeg_custom_output_fun custom_output = [](j_common_ptr) {};

	// 初始化缓冲区并填充压缩图像信息的纯虚函数
	virtual void start_output(jpeg_compress_struct& cinfo) = 0;

	// 从源图像获取数据并更新缓冲区的纯虚函数
	virtual void get_pixel_rows(JDIMENSION num_scanlines) = 0;

	virtual ~jpeg_compress_interface() = default;
};

/**
 * @brief 默认的JPEG压缩实现，继承自jpeg_compress_interface
 */
IMAGEWRAP_API struct jpeg_compress_default : jpeg_compress_interface {
	// 引用到源图像矩阵
	const fs_image_matrix& matrix;
	// 每行的字节数
	uint32_t row_stride;
	// 当前正在处理的行号
	JDIMENSION next_line;

	// 构造函数，初始化必要的参数
	jpeg_compress_default(const fs_image_matrix& matrix);

	// 实现开始输出的虚函数
	void start_output(jpeg_compress_struct& cinfo) override;

	// 实现获取像素行的虚函数
	void get_pixel_rows(JDIMENSION num_scanlines) override;
};

/**
 * @brief 图像解压缩接口类，定义解压操作的基本接口
 */
IMAGEWRAP_API struct jpeg_decompress_interface {
	// 用于存储图像扫描线行指针的缓冲区
	std::vector<JSAMPROW> buffer;

	// 自定义输出参数的函数对象
	jpeg_custom_output_fun custom_output = [](j_common_ptr) {};

	// 初始化并填充解压缩图像信息的纯虚函数
	virtual void start_output(const jpeg_decompress_struct& cinfo) = 0;

	// 将解压缩数据写入图像内存区域的纯虚函数
	virtual void put_pixel_rows(JDIMENSION num_scanlines) = 0;

	virtual ~jpeg_decompress_interface() = default;
};

/**
 * @brief 默认的JPEG解压缩实现，继承自jpeg_decompress_interface
 */
IMAGEWRAP_API struct jpeg_decompress_default : public jpeg_decompress_interface {
	// 解压缩后的图像矩阵
	fs_image_matrix matrix;
	// 每行的字节数
	uint32_t row_stride;
	// 当前正在处理的目标图像行
	JDIMENSION next_line;

	// 构造函数，进行参数对齐初始化
	jpeg_decompress_default(uint8_t align);
	jpeg_decompress_default();

	// 实现开始输出的虚函数
	void start_output(const jpeg_decompress_struct& dinfo) override;

	// 实现写入像素行的虚函数
	void put_pixel_rows(JDIMENSION num_scanlines) override;

	virtual ~jpeg_decompress_default() = default;
};

/**
 * @brief 将图像压缩为JPEG格式，并通过回调返回结果
 *
 * @param compress_instance 压缩接口实例
 * @param finish_output 处理压缩生成的输出的回调函数
 * @param quality 压缩质量（0-100）
 */
IMAGEWRAP_API void save_jpeg_mem(jpeg_compress_interface& compress_instance,
	const mem_finish_output_fun& finish_output,
	const unsigned int quality = 100);

/**
 * @brief 将图像压缩为JPEG格式，允许自定义设置，并通过回调返回结果
 *
 * @param matrix 源图像矩阵
 * @param finish_output 处理压缩生成的输出的回调函数
 * @param quality 压缩质量（0-100）
 * @param custom 自定义输出参数的函数
 */
IMAGEWRAP_API void save_jpeg_mem(const fs_image_matrix& matrix,
	const mem_finish_output_fun& finish_output,
	const unsigned int quality = 100,
	const jpeg_custom_output_fun& custom = jpeg_custom_output_default);

/**
 * @brief 从JPEG数据中解压缩图像，并通过接口实例处理解压缩数据
 *
 * @param jpeg_data JPEG数据指针
 * @param size JPEG数据大小
 * @param decompress_instance 解压缩接口实例
 */
IMAGEWRAP_API void load_jpeg_mem(const uint8_t* jpeg_data, size_t size, jpeg_decompress_interface& decompress_instance);

/**
 * @brief 从JPEG数据中解压缩图像，返回图像矩阵，并允许进行自定义设置
 *
 * @param jpeg_data JPEG数据指针
 * @param size JPEG数据大小
 * @param custom 自定义输出参数的函数
 * @return 解压缩后的图像矩阵
 */
IMAGEWRAP_API fs_image_matrix load_jpeg_mem(const uint8_t* jpeg_data, size_t size,
	const jpeg_custom_output_fun& custom = jpeg_custom_output_default);



#if 0
/**
 * @brief 将图像压缩为灰阶JPEG格式，并通过回调返回结果
 *
 * @param matrix 源图像矩阵
 * @param finish_output 处理压缩生成的输出的回调函数
 * @param quality 压缩质量（0-100）
 */
IMAGEWRAP_API void save_jpeg_gray_mem(const fs_image_matrix& matrix,
	const mem_finish_output_fun& finish_output,
	const unsigned int quality = 100);
#endif

#endif 